﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using GoodStuff;

namespace GoodStuff.UnitTests
{
    [TestFixture]
    public class DependencyInjection
    {
        [Test]
        public void TestResolveSimple()
        {
            Container container = new Container();
            container.Register<IFoo>(c => new Foo());

            var x = container.Resolve<IFoo>() as Foo;

            Assert.IsNotNull(x);
            Assert.IsTrue(x is Foo);
        }

        [Test]
        [ExpectedException(typeof(ResolutionException))]
        public void UnregisteredResolve()
        {
            Container container = new Container();
            var x = container.Resolve<IFoo>();
        }

        [Test]
        public void RegisterArguments()
        {
            Container container = new Container();
            container.Register<IFoo>(c => new FooBar("Hi"));

            var x = container.Resolve<IFoo>() as FooBar;

            Assert.IsNotNull(x);
            Assert.IsTrue(x is FooBar);
        }

        [Test]
        public void RegisterNesteds()
        {
            Container container = new Container();
            container.Register<IBar>(c => new Bar(c.Resolve<IFoo>()));
            container.Register<IFoo>(c => new Foo());

            var x = container.Resolve<IBar>() as Bar;

            Assert.IsNotNull(x);
            Assert.IsTrue(x is Bar);
            Assert.IsNotNull(((Bar)x).Foo);
        }

        [Test]
        public void TestSingleInstance()
        {
            Container container = new Container();
            container.Register<IFoo>(InstanceMode.Reuse, c => new Foo());

            var x = container.Resolve<IFoo>();
            var y = container.Resolve<IFoo>();

            Assert.AreSame(x, y);            
        }


        [Test]
        public void TestOneArgument()
        {
            Container container = new Container();
            container.Register<IFoo, string>((c,s) => new FooBar(s));

            var x = container.Resolve<IFoo, string>("argument");
        }

        [Test]
        public void TestRegisteredWithAndWithoutArgument()
        {
            Container container = new Container();
            container.Register<IFoo>( c => new FooBar());
            container.Register<IFoo, string>((c, s) => new FooBar(s));

            var x = container.Resolve<IFoo, string>("argument") as FooBar ;
            var y = container.Resolve<IFoo>() as FooBar;

            Assert.AreNotSame(x, y);

            Assert.IsTrue(x is FooBar);
            Assert.AreEqual(x.Arg1, "argument");
            Assert.AreEqual(y.Arg1, null);
        }

        [Test]
        public void PlayingWithEnums()
        {
            Container container = new Container();
            container.Register<IFoo>((InstanceMode)39023, null);
        }

        [Test]
        [ExpectedException(typeof(ResolutionException))]
        public void PlayingWithEnumsFailsOnResolve()
        {
            Container container = new Container();
            container.Register<IFoo>((InstanceMode)39023, null);

            var foo = container.Resolve<IFoo>();
        }
                
      
        public interface IFoo
        { 
        }

        public interface IBar
        {
        }

        public class Foo: IFoo
        {
        }
        
        public class FooBar : IFoo
        {
            public FooBar()
            {

            }

            public FooBar(string argument)
            {
                Arg1 = argument;
            }

            public string Arg1 { get; private set; }
        }

        public class Bar : IBar
        {
            public Bar(IFoo child)
            {
                Foo = child;
            }

            public IFoo Foo { get; private set; }
        }
    }
}
